//
// Created by root on 17-3-10.
//

#ifndef HIKVISIONCTRL_HIKV_CTRL_H
#define HIKVISIONCTRL_HIKV_CTRL_H

#include <iostream>
#include <list>
#include <vector>
#include <mosquittopp.h>
#include "json.h"
#include "ctrl_cfg.h"
#include "hikv_api.h"
#include "ctrl_spdlog.h"

#define MQTT_PUB_CLIENT_CTRL  0
#define MQTT_PUB_BOARDCAST    1
#define MQTT_PUB_MAX          2
#define MQTT_PUB_CLIENT_SBUF  3

#define MQTT_SUB_CLIENT_CTRL  0
#define MQTT_SUB_CLIENT_STAT  1
#define MQTT_SUB_CLIENT_RAW   2
#define MQTT_SUB_CLIENT_SBUF  3
#define MQTT_SUB_REPORT       4
#define MQTT_SUB_MAX          5
#define TopicRoot             "/hikvcam"
#define MQSIZE                128

const std::string TYPE_CURL = "curl";
const std::string TYPE_FTP = "ftp";

class CtrlApp {
public:
    enum UPLOAD_MODE{
        RAW_MODE = 1,
        JSON_MODE,
        MPACK_MODE,
    };
    typedef struct position_info {
        float lng;
        float lat;
    } POSITION_INFO_ST;
    typedef struct picture_parm {
        float rotate_angle;
        uint32_t rotate_cond;
        int draw_x_coordinate;
        int draw_y_coordinate;
        char draw_text[256];
        uint32_t draw_color_r;
        uint32_t draw_color_g;
        uint32_t draw_color_b;
        uint32_t draw_text_size_px;
        int resize_pdx;
        int resize_pdy;
        int resize_pdz;
        int resize_pdv;
        uint32_t resize_interp_type;
        POSITION_INFO_ST position;
    } PICTURE_PARM_ST;

    CtrlApp();
    ~CtrlApp();

    void set_position_info_st(POSITION_INFO_ST position_st);
    POSITION_INFO_ST get_position_info_st();
    void set_picture_parm_st(Json::Value &parm_json);
    PICTURE_PARM_ST get_picture_parm_st();

    bool picture_process(std::string picture_name);
    static int iterator_imgfile_callback(const char *fpath, const struct stat *sb, int typeflag);
    bool upload_picture_by_curl(std::string upload_url, std::string username, std::string password, uint32_t period);
    bool upload_picture_by_ftp(std::string upload_url, std::string username, std::string password, uint32_t period);
    bool timer_delete_cache_file();

    CtrlCfg *pctrl_cfg;

private:
    POSITION_INFO_ST _position_st;
    PICTURE_PARM_ST _picture_parm_st;
    static std::vector<std::string> _imgfile_vec;
};

class CtrlMqtt : public mosqpp::mosquittopp
{
public:
    enum TOPIC_T {
        TOPIC_SUBSCRIBE,
        TOPIC_PUBLISH
    };

protected:
    bool m_run;

    std::string m_api_ver="1.0";

public:
    char mqtt_sub[MQTT_SUB_MAX][MQSIZE];
    char mqtt_pub[MQTT_PUB_MAX][MQSIZE];
    std::list<std::string > mhikv_subscribe_topics;
    std::list<std::string > mhikv_publish_topics;

    std::string pic_path;
    CtrlCfg *pctrl_cfg;
    HikvisionAPI *phikv_api;
    CtrlApp *pctrl_app;

    CtrlMqtt(std::string id);
    bool init();
    bool start();
    void release();
    void stop() { m_run=false; }

    void on_connect(int rc);

    void on_disconnect(int rc);

    void on_subscribe(int mid, int qos_count, const int *granted_qos);

    void on_unsubscribe(int mid);


    void on_message(const struct mosquitto_message *msg) ;

    void add_topics(std::string method, std::string topic, TOPIC_T type) ;

    void clear_topics(TOPIC_T type) ;

    void save_topics();

    int start_mqtt_cycle();

    bool mqttctrl_jpgsnap_get_stream(uint32_t channel, char *jpgbuf, uint32_t jpglen, uint32_t num);
    bool upload_jpgsnap_by_mpack();

    int32_t m_mqtt_protocol=MQTT_PROTOCOL_V311;
    void set_protocol(int32_t v){
        if (m_mqtt_protocol!=v && (v==MQTT_PROTOCOL_V311 || v==MQTT_PROTOCOL_V31)){
            m_mqtt_protocol=v;
        }
        //disconnect();
        if (opts_set(MOSQ_OPT_PROTOCOL_VERSION,&m_mqtt_protocol)!=MOSQ_ERR_SUCCESS){
            SpdLog::console->info("mqtt not set protocol version: {0}", m_mqtt_protocol);
        }else{
            SpdLog::console->info("mqtt set protocol version: {0}", m_mqtt_protocol);
        }
        //reconnect();
    }

private:
    bool mqtt_run = true;
    bool create_picdir(int len, const char *jpgbufer);
};

#endif //HIKVISIONCTRL_HIKV_CTRL_H